﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using blackhouse.BlackApart.Business.Apartments;
using blackhouse.BlackApart.Data;
using blackhouse.BlackApart.Business.Reservations;
using blackhouse.BlackApart.Business.Calendar;
using blackhouse.BlackApart.Business.Payments;
using blackhouse.BlackApart.Business.Prices;
using blackhouse.BlackApart.Business.Furnitures;
using blackhouse.BlackApart.Business.Opinions;
using blackhouse.BlackApart.Business.MailTemplate;
using blackhouse.BlackApart.Business.PushMails;
using blackhouse.BlackApart.Business.Places;
using blackhouse.BlackApart.Business.Company;
using blackhouse.BlackApart.Business.Newsletter;
using blackhouse.AsyncMail.Business.Data;
using blackhouse.BlackApart.Business.Cities;
using blackhouse.BlackApart.Business.ApartmentServices;

namespace blackhouse.BlackApart.Business {
    public abstract class Factory : blackhouse.InstanceFactory<Factory> {

        #region INSTANCE

        public static Factory Instance() {
            return Instance("ApartsFactory");
        }

        #endregion

        #region Methods

        public virtual IApartmentGroup GetApartmentGroup(int groupId) {
            return new DaApartmentGroup(this.GetDataFactory().GetApartmentDataGroup(), groupId);
        }

        public virtual IApartmentGroup GetApartmentGroup() {
            return new DaApartmentGroup(this.GetDataFactory().GetApartmentDataGroup());
        }

        public virtual IApartment GetApartment() {
            return new DaApartment(this.GetDataFactory().GetApartmentData());
        }

        public virtual IApartment GetApartment(int apartmentId) {
            return new DaApartment(this.GetDataFactory().GetApartmentData(), apartmentId);
        }

        public virtual IApartmentLocation GetApartmentLocation() {
            return new DaApartmentLocation(this.GetDataFactory().GetApartmentLocationData());
        }

        public virtual IApartmentLocation GetApartmentLocation(int locationId) {
            return new DaApartmentLocation(this.GetDataFactory().GetApartmentLocationData(), locationId);
        }

        //public virtual ICalendar GetApartmentCalendar(IApartment apartment, DateTime startDate, DateTime endDate) {
        //    return new DaApartmentCalendar(this.GetReservationData(), apartment, startDate, endDate);
        //}

        public virtual IClient GetClient(int clientId) {
            return new DaClient(this.GetDataFactory().GetReservationData(), clientId);
        }

        public virtual IPaymentType GetPaymentType() {
            return new DaPaymentType(this.GetDataFactory().GetReservationData());
        }

        public virtual IPaymentType GetPaymentType(int paymentTypeId) {
            return new DaPaymentType(this.GetDataFactory().GetReservationData(), paymentTypeId);
        }

        //public virtual IUserApartmentsReservation CreateUserApartmentsReservation() {
        //    return new DaUserApartmentsReservation(this.GetReservationData());
        //}

        //public IUserApartmentsReservation GetUserApartmentsReservation(int reservationId) {
        //    return new DaUserApartmentsReservation(this.GetReservationData(), reservationId);
        //}

        public virtual IApartmentPrice GetApartmentGroupPrice(IApartmentGroup group) {
            IApartment ap = group.GetApartments().FirstOrDefault();
            return (ap == null) ? null : GetApartmentPrice(ap.Id);
        }

        public virtual IApartmentPrice GetApartmentPrice(int apartmentId) {
            return new DaApartmentDbPrice(apartmentId, this.GetDataFactory().GetPricesData());
        }

        public IPriceRabat GetPriceRabat() {
            return this.GetPriceRabat(0);
        }

        public virtual IPriceRabat GetPriceRabat(int apartmentTypeId) {
            return new DaPriceRabat(this.GetDataFactory().GetPricesData(), apartmentTypeId);
        }

        public virtual IPriceRabat GetPriceRabat(PriceRabatData data) {
            return new DaPriceRabat(this.GetDataFactory().GetPricesData(), data);
        }

        public IPriceRabat GetPriceRabat(string rabatKey) {
            return this.GetPriceRabat().GetRabat(rabatKey);
        }

        public IPriceRabat GetPriceRabat(string rabatKey, int apartmentTypeId) {
            return this.GetPriceRabat(apartmentTypeId).GetRabat(rabatKey);
        }

        public virtual IFurniture GetFurniture() {
            return new DaFurniture(this.GetDataFactory().GetFurnitureData());
        }

        public virtual IFurniture GetFurniture(int furnitureId) {
            return new DaFurniture(this.GetDataFactory().GetFurnitureData(), furnitureId);
        }

        public virtual IApartmentPhoto GetApartmentPhoto() {
            return new DaApartmentPhoto(this.GetDataFactory().GetApartmentData());
        }

        public virtual IOpinionCategory GetOpinionCategory() {
            return new DaOpinionCategory(this.GetDataFactory().GetOpinionsData());
        }

        public virtual IOpinion GetOpinion() {
            return new DaOpinion(this.GetDataFactory().GetOpinionsData());
        }

        public virtual IOpinion GetOpinion(int opinionId) {
            return new DaOpinion(this.GetDataFactory().GetOpinionsData(), opinionId);
        }

        public virtual IOpinionToReservation CreateOpinionToReservationTrans() {
            return new DaOpinionToReservation(this.GetDataFactory().GetOpinionsData());
        }

        public virtual StatisticsOpinion GetStatisticsOpinion() {
            return new StatisticsOpinion(this.GetDataFactory().GetOpinionsData());
        }

        public virtual IMailTemplate GetMailTemplate(int templateId) {
            return new DaMailTemplate(this.GetDataFactory().GetMailTemplateData(), templateId);
        }

        public virtual IPushMail MakePushMail() {
            return this.MakePushMail(0);
        }

        public virtual IPushMail MakePushMail(int id) {
            return new DaPushMail(this.GetDataFactory().GetPushMailData(), id);
        }

        public virtual IPlace GetPlace() {
            return new DaPlace(this.GetDataFactory().GetPlaceData());
        }

        public virtual ISubscriber GetSubscriber(string email) {
            return new DaSubscriber(this.GetDataFactory().GetNewsletterDataAccess(), email);
        }

        public virtual ISubscriber GetSubscriber(Guid uniqueId) {
            return new DaSubscriber(this.GetDataFactory().GetNewsletterDataAccess(), uniqueId);
        }

        //public abstract IUserReservation CreateUserReservation();

        //public abstract IReservationType GetReservationType(string id);

        public abstract ICompany GetCompany();

        public abstract IASyncMailDataAccess GetASyncMailData();

        public abstract ApartmentSortModel GetSorting();

        public virtual string GetPreFolderEvaluation() {
            return "";
        }

        public virtual SiteCity GetSiteCity() {
            return new SiteCity();
        }

        public virtual IWebReservation CreateWebReservation() {
            return new DaWebReservation(this.GetDataFactory().GetReservationData());
        }

        public virtual IWebReservation GetWebReservation(int reservationId) {
            return new DaWebReservation(this.GetDataFactory().GetReservationData(), reservationId);
        }

        public virtual IWebReservation GetWebReservation(Guid reservationGuid) {
            return new DaWebReservation(this.GetDataFactory().GetReservationData(), reservationGuid);
        }

        public virtual IWebReservation GetWebReservation(string reservationNumber) {
            return new DaWebReservation(this.GetDataFactory().GetReservationData(), reservationNumber);
        }

        public virtual IAdditionalService GetAdditionalService() {
            return new DaAdditionalService(this.GetDataFactory().GetAdditionalServicesData());
        }

        internal AvabilityOfApartmentTypes GetAvabilityOfApartmentTypes(int groupId, DateTime fromDay, DateTime toDay) {
            AvabilityOfApartmentTypes av = new AvabilityOfApartmentTypes(this.GetDataFactory().GetReservationData(), groupId, fromDay, toDay);
            return av;
        }

        public abstract IDataFactory GetDataFactory();

        #endregion

    }
}
